#include "S5Debug.h"
#include <KDebug.h>
#include <KNamespace.h>
#include <cctype>
#include <sstream>

K_ANONYMOUS_NAMESPACE_BEG

const char HEX_NUMBER[] = "0123456789ABCDEF";

inline size_t byteHigh(unsigned char byte)  { return (byte >> 4) & 0xf; }
inline size_t byteLow(unsigned char byte)   { return byte & 0xf; }

K_ANONYMOUS_NAMESPACE_END

void s5_debug_hex(const void *data, size_t length, const char *title, const KIpAddress *addr, size_t width)
{
    if (data && length > 0 && width > 0) {
        unsigned char c;
        const unsigned char *ch = reinterpret_cast<const unsigned char *>(data);
        std::ostringstream oss;
        size_t count;
        if (title) {
            oss << title;
            if (addr) {
                oss << '(' << addr->ip() << ':' << addr->port() << ')';
            }
            oss << "\r\n";
        }
        oss << "{\r\n";
        do {
            count = min(length, width); // WinDef, not std::min
            oss << "   ";
            for (size_t i = 0; i < count; ++i) {
                c = ch[i];
                oss << ' ' << HEX_NUMBER[byteHigh(c)] << HEX_NUMBER[byteLow(c)];
            }
            for (size_t i = 0; i < width - count; ++i) {
                oss << "   ";
            }
            oss << "    ";
            for (size_t i = 0; i < count; ++i) {
                c = ch[i];
                if (isspace(c)) {
                    oss << '.';
                } else if (isprint(c)) {
                    oss << c;
                } else {
                    oss << '.';
                }
            }
            oss << "\r\n";
            length -= count;
            ch += count;
        } while (length > 0);
        oss << "}\r\n";
        KTraceMsg("%s", oss.str().c_str());
    }
}